জাভার Generics এবং Reflection API একত্রে ব্যবহার করলে জেনেরিক টাইপের অবজেক্ট সম্পর্কে রানটাইমে বিস্তারিত তথ্য পাওয়া যায়। তবে জেনেরিক্সের Type Erasure মেকানিজমের কারণে টাইপ সম্পর্কিত তথ্য কম্পাইল-টাইম থেকে রানটাইমে হারিয়ে যায়। Reflection API এর সাহায্যে এই সীমাবদ্ধতা আংশিকভাবে মোকাবিলা করা যায়।
Generics এবং Type Erasure
জাভার জেনেরিক্স কম্পাইল-টাইম টাইপ চেকিং করে এবং রানটাইমে টাইপ ইনফরমেশন মুছে ফেলে। উদাহরণস্বরূপ:
List<String> stringList = new ArrayList<>();
List<Integer> integerList = new ArrayList<>();
System.out.println(stringList.getClass() == integerList.getClass()); // Output: true
কেন এমন হয়?
List<String>এবংList<Integer>কম্পাইল-টাইমে আলাদা মনে হয়।- রানটাইমে উভয়ই
Listহিসাবে আচরণ করে।
Reflection API দিয়ে Generics ব্যবহার
Reflection API ব্যবহার করে জেনেরিক ক্লাস বা মেথডের টাইপ সম্পর্কে তথ্য পাওয়া যায়। এর জন্য Type, ParameterizedType, এবং TypeVariable ইন্টারফেসগুলো গুরুত্বপূর্ণ।
Generics এবং Reflection API উদাহরণ
1. জেনেরিক ক্লাসে টাইপ ইনফরমেশন পাওয়া
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
class GenericClass<T> {
private List<T> items;
}
public class ReflectionGenericExample {
public static void main(String[] args) throws NoSuchFieldException {
Field field = GenericClass.class.getDeclaredField("items");
Type genericType = field.getGenericType();
if (genericType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericType;
Type[] typeArguments = parameterizedType.getActualTypeArguments();
for (Type type : typeArguments) {
System.out.println("Generic Type Argument: " + type.getTypeName());
}
}
}
}
আউটপুট:
Generic Type Argument: T
2. জেনেরিক মেথডে টাইপ ইনফরমেশন পাওয়া
import java.lang.reflect.Method;
import java.lang.reflect.Type;
class GenericMethodExample {
public <T> void printDetails(T item) {
System.out.println(item);
}
}
public class ReflectionGenericMethod {
public static void main(String[] args) throws NoSuchMethodException {
Method method = GenericMethodExample.class.getMethod("printDetails", Object.class);
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type type : genericParameterTypes) {
System.out.println("Parameter Type: " + type.getTypeName());
}
Type returnType = method.getGenericReturnType();
System.out.println("Return Type: " + returnType.getTypeName());
}
}
আউটপুট:
Parameter Type: T
Return Type: void
3. জেনেরিক টাইপ ইনফরমেশন দিয়ে অ্যারে তৈরি
import java.lang.reflect.Array;
public class GenericArrayWithReflection<T> {
private T[] array;
@SuppressWarnings("unchecked")
public GenericArrayWithReflection(Class<T> clazz, int size) {
array = (T[]) Array.newInstance(clazz, size);
}
public void set(int index, T value) {
array[index] = value;
}
public T get(int index) {
return array[index];
}
public static void main(String[] args) {
GenericArrayWithReflection<String> genericArray = new GenericArrayWithReflection<>(String.class, 5);
genericArray.set(0, "Hello");
genericArray.set(1, "World");
System.out.println(genericArray.get(0)); // Output: Hello
System.out.println(genericArray.get(1)); // Output: World
}
}
Generics এবং Reflection-এর সীমাবদ্ধতা
- Type Erasure:
- কম্পাইল-টাইমে জেনেরিক টাইপ ইনফরমেশন থাকে।
- রানটাইমে
List<String>এবংList<Integer>একইListটাইপে রূপান্তরিত হয়।
Instanceofচেক করা যায় না:List<String> stringList = new ArrayList<>(); if (stringList instanceof List<String>) { // Compile-time error // Do something }- Runtime Type Checking:
- জেনেরিক ইনফরমেশন রানটাইমে পাওয়া কঠিন।
Generics এবং Reflection-এর ব্যবহার ক্ষেত্র
- Framework Development:
- Hibernate, Spring, ইত্যাদি ফ্রেমওয়ার্কে রানটাইম টাইপ চেকিংয়ের জন্য Reflection API এবং Generics ব্যবহৃত হয়।
- Generic Libraries:
- জেনেরিক কোডকে টাইপ-সেইফ রাখতে এবং ইনফরমেশন চেক করতে ব্যবহৃত হয়।
- Serialization/Deserialization:
- JSON বা XML প্রক্রিয়ায় টাইপ ইনফরমেশন প্রয়োজন হলে Reflection এবং Generics একত্রে ব্যবহার করা হয়।
Generics এবং Reflection API একত্রে ব্যবহার করলে টাইপ ইনফরমেশন এবং রানটাইম চেকিং আরও কার্যকর হয়। তবে Type Erasure সীমাবদ্ধতার কারণে টাইপ সম্পর্কিত কিছু কাজ জটিল হয়ে যায়। Reflection এবং Generics-এর সঠিক ব্যবহারে বড় প্রজেক্টে আরও নিরাপদ এবং কার্যকরী সমাধান তৈরি করা সম্ভব।
Reflection API এবং Generics একত্রিতভাবে জাভায় টাইপ ডাইনামিক্সের উপর আরো গভীর নিয়ন্ত্রণ এবং তথ্য পাওয়ার সুযোগ দেয়। Reflection ব্যবহার করে জেনেরিক ক্লাস, মেথড, এবং ফিল্ডের টাইপ ইনফরমেশন রানটাইমে অ্যাক্সেস করা যায়। এটি বিশেষত এমন ক্ষেত্রে দরকারী যেখানে জেনেরিক টাইপ সম্পর্কিত ডায়নামিক অপারেশন প্রয়োজন।
Generics এবং Type Erasure
জাভায় জেনেরিক্স টাইপ ইনফরমেশন Compile-Time-এ চেক করা হয় এবং Type Erasure এর মাধ্যমে রানটাইমে টাইপের তথ্য মুছে যায়। তবে, Reflection API ব্যবহার করে সীমিত কিছু ক্ষেত্রে এই টাইপ ইনফরমেশন রানটাইমে পুনরুদ্ধার করা সম্ভব।
Reflection API এর সাথে Generics এর Integration
1. Generic Class এর Type Parameters বের করা
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
class GenericClass<T> {
// Empty class
}
public class Main {
public static void main(String[] args) {
GenericClass<String> obj = new GenericClass<>();
Type superclass = obj.getClass().getGenericSuperclass();
if (superclass instanceof ParameterizedType) {
ParameterizedType parameterized = (ParameterizedType) superclass;
Type[] typeArgs = parameterized.getActualTypeArguments();
for (Type type : typeArgs) {
System.out.println("Type Argument: " + type.getTypeName());
}
} else {
System.out.println("No Parameterized Type found.");
}
}
}
আউটপুট:
No Parameterized Type found.
কারণ: রানটাইমে জাভা টাইপ মুছে ফেলে। Type Erasure এর কারণে এই উদাহরণটি সরাসরি কাজ করে না।
2. Generic Method এবং এর Parameter Types বের করা
import java.lang.reflect.Method;
import java.lang.reflect.Type;
public class GenericMethodExample {
public <T> void genericMethod(T param) {
System.out.println(param);
}
public static void main(String[] args) throws Exception {
Method method = GenericMethodExample.class.getMethod("genericMethod", Object.class);
System.out.println("Method Name: " + method.getName());
Type[] parameterTypes = method.getGenericParameterTypes();
for (Type type : parameterTypes) {
System.out.println("Parameter Type: " + type.getTypeName());
}
}
}
আউটপুট:
Method Name: genericMethod
Parameter Type: T
3. Generic Type Information সহ Collection Analysis
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
class GenericHolder {
public List<String> stringList;
}
public class Main {
public static void main(String[] args) throws NoSuchFieldException {
Field field = GenericHolder.class.getField("stringList");
Type type = field.getGenericType();
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] typeArguments = parameterizedType.getActualTypeArguments();
for (Type arg : typeArguments) {
System.out.println("Generic Type Argument: " + arg.getTypeName());
}
}
}
}
আউটপুট:
Generic Type Argument: java.lang.String
Complex Example: Generic Class with Multiple Parameters
কোড:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
}
public class Main {
public static void main(String[] args) {
Pair<String, Integer> pair = new Pair<>("Age", 30);
Type superclass = pair.getClass().getGenericSuperclass();
if (superclass instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) superclass;
Type[] typeArguments = parameterizedType.getActualTypeArguments();
System.out.println("Type Parameters:");
for (Type type : typeArguments) {
System.out.println(type.getTypeName());
}
}
}
}
আউটপুট:
Type Parameters:
java.lang.String
java.lang.Integer
Wildcard এবং Reflection
কোড:
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
class WildcardHolder {
public List<? extends Number> numbers;
}
public class Main {
public static void main(String[] args) throws NoSuchFieldException {
Field field = WildcardHolder.class.getField("numbers");
ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
Type[] typeArguments = parameterizedType.getActualTypeArguments();
for (Type type : typeArguments) {
System.out.println("Wildcard Type: " + type.getTypeName());
}
}
}
আউটপুট:
Wildcard Type: ? extends java.lang.Number
Reflection এর সীমাবদ্ধতা
- Type Erasure: জাভা রানটাইমে টাইপ ইনফরমেশন মুছে ফেলে।
- Raw Type Handling: রো টাইপের ক্ষেত্রে নির্ভুল তথ্য পাওয়া যায় না।
- Performance Impact: Reflection ব্যবহারের ফলে পারফরম্যান্স কিছুটা কমতে পারে।
- Reflection API এর সাথে জেনেরিক্স ব্যবহার করলে রানটাইমে জেনেরিক টাইপ ইনফরমেশন পাওয়া সম্ভব।
- Type Erasure-এর কারণে কিছু সীমাবদ্ধতা রয়েছে।
- বড় প্রজেক্টে ডাইনামিক ডেটা হ্যান্ডলিং বা ফ্রেমওয়ার্ক তৈরি করার ক্ষেত্রে Reflection এবং Generics এর Integration অপরিহার্য।
জাভা জেনেরিক্স ব্যবহার করে Class এবং Method সম্পর্কিত তথ্য এক্সট্রাক্ট করা বেশ কার্যকর, বিশেষ করে যখন Reflection API এর সাথে একত্রে ব্যবহৃত হয়। এটি জেনেরিক ক্লাস ও মেথডের টাইপ প্যারামিটার সম্পর্কিত তথ্য ডাইনামিকভাবে অ্যাক্সেস করতে সাহায্য করে।
Reflection এর সাহায্যে জেনেরিক তথ্য এক্সট্রাক্ট করা
জাভার java.lang.reflect প্যাকেজটি টাইম প্যারামিটার, টাইপ বাউন্ড, এবং জেনেরিক প্যারামিটার সম্পর্কিত তথ্য বের করার সুযোগ দেয়।
1. Generics সহ Class Information Extraction
উদাহরণ:
import java.lang.reflect.Type;
import java.lang.reflect.ParameterizedType;
import java.util.List;
public class GenericClassInfo<T> {
public static void main(String[] args) {
// Anonymous subclass to retain generic type information
GenericClassInfo<List<String>> instance = new GenericClassInfo<List<String>>() {};
// Extract the superclass type
Type superClass = instance.getClass().getGenericSuperclass();
// Check if the type is parameterized
if (superClass instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) superClass;
// Get actual type arguments
Type[] typeArguments = parameterizedType.getActualTypeArguments();
for (Type type : typeArguments) {
System.out.println("Type argument: " + type.getTypeName());
}
}
}
}
আউটপুট:
Type argument: java.util.List<java.lang.String>
2. Generics সহ Method Information Extraction
উদাহরণ:
import java.lang.reflect.Method;
import java.lang.reflect.Type;
public class GenericMethodInfo {
public <T> void genericMethod(T param) {}
public static void main(String[] args) throws NoSuchMethodException {
// Get the method
Method method = GenericMethodInfo.class.getMethod("genericMethod", Object.class);
// Get the generic parameter types
Type[] parameterTypes = method.getGenericParameterTypes();
for (Type type : parameterTypes) {
System.out.println("Parameter type: " + type.getTypeName());
}
}
}
আউটপুট:
Parameter type: T
3. Extracting Return Type of Generic Methods
উদাহরণ:
import java.lang.reflect.Method;
import java.lang.reflect.Type;
public class GenericReturnType {
public <T> T getGenericValue() {
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
// Get the method
Method method = GenericReturnType.class.getMethod("getGenericValue");
// Extract the return type
Type returnType = method.getGenericReturnType();
System.out.println("Return type: " + returnType.getTypeName());
}
}
আউটপুট:
Return type: T
Generics এর মাধ্যমে Complex Class Structures Information Extraction
Generics সহ Nested Class এবং Multiple Type Extraction
উদাহরণ:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
public class ComplexGenericClass<A, B> {
public static void main(String[] args) {
ComplexGenericClass<Map<String, Integer>, Double> instance = new ComplexGenericClass<>() {};
Type superClass = instance.getClass().getGenericSuperclass();
if (superClass instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) superClass;
Type[] typeArguments = parameterizedType.getActualTypeArguments();
for (Type type : typeArguments) {
System.out.println("Type argument: " + type.getTypeName());
}
}
}
}
আউটপুট:
Type argument: java.util.Map<java.lang.String, java.lang.Integer>
Type argument: java.lang.Double
Annotation এর সাথে জেনেরিক্স এবং মেথড ইনফরমেশন Extraction
উদাহরণ:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
@Retention(RetentionPolicy.RUNTIME)
@interface GenericAnnotation {}
public class GenericAnnotationExample {
@GenericAnnotation
public <T> T annotatedGenericMethod(T param) {
return param;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = GenericAnnotationExample.class.getMethod("annotatedGenericMethod", Object.class);
// Check if the method has the annotation
if (method.isAnnotationPresent(GenericAnnotation.class)) {
System.out.println("Method has GenericAnnotation");
// Extract the generic return type
System.out.println("Return type: " + method.getGenericReturnType());
}
}
}
আউটপুট:
Method has GenericAnnotation
Return type: T
প্রসঙ্গ ও সীমাবদ্ধতা
প্রসঙ্গ:
- Type Erasure: জেনেরিক্স টাইপ তথ্য Runtime-এ মুছে যায়, তবে Reflection ব্যবহার করে কিছু তথ্য পুনরুদ্ধার করা সম্ভব।
- Reusable Code: জেনেরিক ক্লাস বা মেথডের টাইপ প্যারামিটার ডাইনামিকভাবে বুঝতে পারলে, কোড আরও রিইউজেবল হয়।
সীমাবদ্ধতা:
- Type Erasure এর কারণে সীমিত ইনফরমেশন:
- Runtime-এ জেনেরিক টাইপ সম্পর্কে সীমিত তথ্য পাওয়া যায়।
- Complexity:
- জটিল জেনেরিক টাইপ বা ইনহেরিটেন্সের ক্ষেত্রে Reflective কোড আরও জটিল হয়ে যায়।
Generics এবং Reflection একত্রে ব্যবহার করে জেনেরিক ক্লাস ও মেথডের টাইপ প্যারামিটার সম্পর্কিত তথ্য ডাইনামিকভাবে বের করা সম্ভব। এটি অ্যাপ্লিকেশন ডেভেলপমেন্টে টাইপ সেফটি বজায় রেখে রিফ্লেকটিভ মেটাডেটা প্রসেসিং সহজ করে।
Type Erasure জাভার জেনেরিক্সের একটি মূল বৈশিষ্ট্য। এটি কম্পাইল টাইমে জেনেরিক তথ্য মুছে ফেলে, ফলে রানটাইমে জেনেরিক টাইপ সম্পর্কিত কোনো তথ্য থাকে না। এই প্রক্রিয়ার কারণে জেনেরিক্সের সাথে Reflection API ব্যবহার করার ক্ষেত্রে কিছু সীমাবদ্ধতা দেখা দেয়।
Type Erasure কী?
Type Erasure হলো জাভার জেনেরিক্সের প্রক্রিয়া, যেখানে:
- জেনেরিক টাইপ প্যারামিটারগুলো কম্পাইল টাইমে মুছে ফেলা হয়।
- জেনেরিক টাইপকে এর বাউন্ড টাইপ (যদি নির্দিষ্ট করা থাকে) বা Object দিয়ে প্রতিস্থাপন করা হয়।
- টাইপ সংক্রান্ত তথ্য শুধুমাত্র কম্পাইল টাইমে বিদ্যমান থাকে, রানটাইমে নয়।
Reflection কী?
Reflection হলো জাভার একটি ফিচার, যা রানটাইমে ক্লাস, মেথড, বা ফিল্ড সম্পর্কে তথ্য পেতে এবং এগুলোতে পরিবর্তন আনতে দেয়।
Type Erasure এর কারণে Reflection এর সীমাবদ্ধতা
1. রানটাইমে জেনেরিক টাইপ তথ্য পাওয়া যায় না
Type Erasure এর ফলে, জেনেরিক টাইপের তথ্য মুছে যায়, তাই রানটাইমে Reflection API দিয়ে সঠিক টাইপ নির্ধারণ করা সম্ভব হয় না।
উদাহরণ:
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) {
try {
Method method = Main.class.getMethod("print", Object.class);
System.out.println("Parameter Type: " + method.getParameterTypes()[0]);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public static <T> void print(T data) {
System.out.println(data);
}
}
আউটপুট:
Parameter Type: class java.lang.Object
ব্যাখ্যা:<T> এর আসল টাইপ রানটাইমে উপস্থিত নেই, ফলে এটি Object এ রূপান্তরিত হয়।
2. Generic Type এর Instantiation সম্ভব নয়
Type Erasure এর কারণে জেনেরিক টাইপ ব্যবহার করে ডাইনামিক ইনস্ট্যান্স তৈরি করা যায় না।
ভুল উদাহরণ:
public class GenericClass<T> {
public void createInstance() {
T instance = new T(); // Compile-time error
}
}
কারণ:
Tএর টাইপ ইনফরমেশন কম্পাইল টাইমে মুছে যায়, তাই রানটাইমেnew T()কাজ করে না।
3. Parameterized Type চেক করা সম্ভব নয়
Reflection ব্যবহার করে একটি জেনেরিক টাইপে প্যারামিটারাইজড টাইপ চেক করা যায় না।
উদাহরণ:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
List<Integer> intList = new ArrayList<>();
System.out.println(stringList.getClass() == intList.getClass()); // True
}
}
আউটপুট:
true
কারণ:
Type Erasure এর ফলে, List<String> এবং List<Integer> এর ক্লাস টাইপ একই (ArrayList)।
4. Generic মেথড Overloading এর সীমাবদ্ধতা
Type Erasure এর কারণে, জেনেরিক মেথড Overloading সম্ভব নয়। কারণ কম্পাইল টাইমে উভয় মেথড একই সিগনেচার ধারণ করে।
ভুল উদাহরণ:
public class GenericExample {
public void print(List<String> list) {
System.out.println("String List");
}
public void print(List<Integer> list) {
System.out.println("Integer List");
}
}
কম্পাইল-টাইম ত্রুটি:
method print(List<String>) and method print(List<Integer>) have the same erasure
Type Erasure এবং Reflection এর কিছু সীমাবদ্ধতা কাটিয়ে ওঠা
1. Helper ক্লাস ব্যবহার করা
রানটাইমে টাইপ তথ্য সংরক্ষণের জন্য Helper ক্লাস বা কনস্ট্রাক্টর ব্যবহার করা যেতে পারে।
উদাহরণ:
import java.lang.reflect.ParameterizedType;
public class GenericClass<T> {
private Class<T> type;
@SuppressWarnings("unchecked")
public GenericClass() {
this.type = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass())
.getActualTypeArguments()[0];
}
public Class<T> getType() {
return type;
}
}
class Main extends GenericClass<String> {
public static void main(String[] args) {
Main main = new Main();
System.out.println("Generic Type: " + main.getType().getName());
}
}
আউটপুট:
Generic Type: java.lang.String
2. Type Token Pattern ব্যবহার করা
Type Token প্যাটার্ন ব্যবহার করে টাইপ ইনফরমেশন ম্যানুয়ালি সরবরাহ করা যেতে পারে।
উদাহরণ:
import java.lang.reflect.Type;
public class TypeToken<T> {
private final Type type;
public TypeToken(Type type) {
this.type = type;
}
public Type getType() {
return type;
}
}
class Main {
public static void main(String[] args) {
TypeToken<List<String>> token = new TypeToken<>(new ArrayList<String>().getClass());
System.out.println("Type: " + token.getType());
}
}
Type Erasure এর কারণে:
- রানটাইমে জেনেরিক টাইপ ইনফরমেশন হারিয়ে যায়।
- Reflection API এর মাধ্যমে জেনেরিক টাইপ পরিচালনা করা সীমিত হয়।
তবে, Helper ক্লাস এবং Type Token এর মতো কৌশল ব্যবহার করে এই সীমাবদ্ধতাগুলি আংশিকভাবে সমাধান করা যায়। Type Erasure জাভার জেনেরিক্সের স্থিতিশীলতা এবং ব্যাকওয়ার্ড কম্প্যাটিবিলিটির জন্য অপরিহার্য হলেও, এটি জেনেরিক প্রোগ্রামিংয়ে কিছু চ্যালেঞ্জ সৃষ্টি করে।
জাভার জেনেরিক্স Compile-time Type Checking সাপোর্ট করে, কিন্তু Runtime Type Checking সরাসরি জেনেরিক টাইপে সম্ভব নয় কারণ জাভার Type Erasure মেকানিজম জেনেরিক টাইপের তথ্য রানটাইমে সরিয়ে ফেলে। তবে, Reflection API ব্যবহার করে জেনেরিক টাইপ সম্পর্কিত কিছু তথ্য রানটাইমে পাওয়া সম্ভব।
Reflection এবং Generics: Runtime Type Checking
Type Erasure সমস্যার কারণ
Type Erasure এর কারণে, জেনেরিক টাইপ রানটাইমে অপ্রাসঙ্গিক হয়ে যায়। উদাহরণ:
import java.util.ArrayList;
import java.util.List;
public class TypeErasureExample {
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
List<Integer> intList = new ArrayList<>();
System.out.println(stringList.getClass() == intList.getClass()); // Output: true
}
}
কারণ:
List<String>এবংList<Integer>উভয় ক্ষেত্রেই রানটাইমে ক্লাসের টাইপ তথ্য মুছে ফেলা হয়। ফলে, উভয় লিস্ট একইArrayListটাইপে পরিণত হয়।
Reflection দিয়ে Generics তথ্য নির্ণয়
Reflection API ব্যবহার করে ক্লাস বা ফিল্ডের জেনেরিক টাইপের তথ্য রানটাইমে জানা যায়।
উদাহরণ ১: ফিল্ডের জেনেরিক টাইপ চেক করা
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
public class GenericReflectionExample {
private List<String> stringList;
public static void main(String[] args) throws NoSuchFieldException {
Field field = GenericReflectionExample.class.getDeclaredField("stringList");
// Check if the field has a generic type
Type genericType = field.getGenericType();
if (genericType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericType;
Type[] typeArguments = parameterizedType.getActualTypeArguments();
// Print the generic type arguments
for (Type type : typeArguments) {
System.out.println("Generic type: " + type.getTypeName());
}
}
}
}
আউটপুট:
Generic type: java.lang.String
উদাহরণ ২: মেথডের জেনেরিক টাইপ চেক করা
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
public class GenericMethodReflection {
public List<Integer> getIntegerList() {
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method method = GenericMethodReflection.class.getMethod("getIntegerList");
// Get the generic return type
Type genericReturnType = method.getGenericReturnType();
if (genericReturnType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericReturnType;
Type[] typeArguments = parameterizedType.getActualTypeArguments();
// Print the generic type arguments
for (Type type : typeArguments) {
System.out.println("Generic return type: " + type.getTypeName());
}
}
}
}
আউটপুট:
Generic return type: java.lang.Integer
Generics এ Runtime Type Checking করার জন্য কাস্টম কোড
যেহেতু জেনেরিক টাইপ সরাসরি চেক করা যায় না, তাই কাস্টম লজিক ব্যবহার করা যেতে পারে।
উদাহরণ: লিস্টের কনটেন্ট টাইপ চেক করা
import java.util.ArrayList;
import java.util.List;
public class RuntimeTypeCheck {
public static <T> boolean isOfType(List<?> list, Class<T> clazz) {
for (Object obj : list) {
if (!clazz.isInstance(obj)) {
return false;
}
}
return true;
}
public static void main(String[] args) {
List<String> stringList = new ArrayList<>();
stringList.add("Hello");
stringList.add("World");
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
System.out.println(isOfType(stringList, String.class)); // Output: true
System.out.println(isOfType(intList, String.class)); // Output: false
}
}
Reflection এবং Annotated Generics
Reflection দিয়ে Annotated Generics এর টাইপও নির্ধারণ করা সম্ভব।
উদাহরণ: Generics এর সাথে Annotated ফিল্ড চেক করা
import java.lang.reflect.Field;
import java.util.List;
public class AnnotatedGenericsExample {
private List<@Deprecated String> annotatedList;
public static void main(String[] args) throws NoSuchFieldException {
Field field = AnnotatedGenericsExample.class.getDeclaredField("annotatedList");
System.out.println("Field: " + field.getName());
System.out.println("Annotated type: " + field.getAnnotatedType());
}
}
আউটপুট:
Field: annotatedList
Annotated type: java.util.List<@java.lang.Deprecated java.lang.String>
Reflection ব্যবহার করার সুবিধা
- জেনেরিক টাইপের তথ্য পেতে: Type Erasure এর সীমাবদ্ধতা কাটিয়ে জেনেরিক টাইপ সম্পর্কিত তথ্য জানা যায়।
- রানটাইম যাচাইকরণ: জেনেরিক টাইপ চেকিং এবং ডায়াগনস্টিক তৈরি করতে কার্যকর।
- ডায়নামিক প্রোগ্রামিং: ডায়নামিক টাইপ-ভিত্তিক অপারেশন এবং ডিবাগিং সহজ হয়।
জাভার জেনেরিক্স রানটাইম টাইপ ইনফরমেশন সরিয়ে ফেলে (Type Erasure), তবে Reflection API ব্যবহার করে জেনেরিক টাইপ সম্পর্কিত তথ্য রানটাইমে নির্ণয় করা সম্ভব। এটি টাইপ ইনফরমেশন অ্যাক্সেস, যাচাইকরণ এবং ডায়নামিক প্রোগ্রামিংয়ে গুরুত্বপূর্ণ ভূমিকা পালন করে।
Read more